#ifndef PROJECTFILE_H
#define PROJECTFILE_H

#include <vector>
#include "globals.h"
#include "prep.h"
#include <wx/dynarray.h>
#include <wx/filename.h>
#include <wx/treectrl.h>
#include <wx/hashset.h>

class M_Code_Project;
class ProjectBuildTarget;
class pfDetails;

WX_DECLARE_HASH_MAP( ProjectBuildTarget*, pfDetails*, wxPointerHash, wxPointerEqual, PFDMap );

struct pfCustomBuild {
  pfCustomBuild() : useCustomBuildCommand( false ) { }
  wxString buildCommand;
  bool useCustomBuildCommand;
};
WX_DECLARE_HASH_MAP( wxString, pfCustomBuild, wxStringHash, wxStringEqual, pfCustomBuildMap );

class ProjectFile;
typedef std::vector<ProjectFile*> ProjectFilesVector;

WX_DEFINE_ARRAY_INT( int, editorFoldLinesArray );

class ProjectFile {
  public:
    ProjectFile( M_Code_Project* prj );
    ~ProjectFile();
    void Rename( const wxString& new_name );
    void AddBuildTarget( const wxString& targetName );
    void RenameBuildTarget( const wxString& oldTargetName, const wxString& newTargetName );
    void RemoveBuildTarget( const wxString& targetName );
    const wxArrayString& GetBuildTargets() const;
    bool ShowOptions( wxWindow* parent );
    wxString GetBaseName() const;
    const wxString& GetObjName();
    void SetObjName( const wxString& name );
    M_Code_Project* GetParentProject() { return project; }
    void UpdateFileDetails( ProjectBuildTarget* target = nullptr );
    const pfDetails& GetFileDetails( ProjectBuildTarget* target );
    void SetFileState( FileVisualState state );
    FileVisualState GetFileState() const;
    void SetUseCustomBuildCommand( const wxString& compilerId, bool useCustomBuildCommand );
    void SetCustomBuildCommand( const wxString& compilerId, const wxString& newBuildCommand );
    bool GetUseCustomBuildCommand( const wxString& compilerId );
    wxString GetCustomBuildCommand( const wxString& compilerId );
    wxFileName file;
    wxString relativeFilename;
    wxString relativeToCommonTopLevelPath;
    bool compile;
    bool link;
    unsigned short int weight;
    bool editorOpen;
    int editorSplit;
    int editorSplitActive;
    int editorSplitPos;
    int editorPos;
    int editorTopLine;
    int editorZoom;
    int editorPos_2;
    int editorTopLine_2;
    int editorZoom_2;
    int editorTabPos;
    wxArrayInt editorFoldLinesArray;
    pfCustomBuildMap customBuild;
    wxString compilerVar;
    wxArrayString buildTargets;
    wxString virtual_path;
    ProjectFile* autoGeneratedBy;
    ProjectFile* AutoGeneratedBy() const { return autoGeneratedBy;}
    void SetAutoGeneratedBy( ProjectFile* TheFile ) { autoGeneratedBy = TheFile; }
    ProjectFilesVector generatedFiles;
    const wxTreeItemId& GetTreeItemId() const { return m_TreeItemId; }
    void SetTreeItemId( wxTreeItemId id ) { m_TreeItemId = id; }
    static int CompareProjectFiles( ProjectFile* item1, ProjectFile* item2 );
  protected:
    friend class M_Code_Project;
    void DoUpdateFileDetails( ProjectBuildTarget* target );
    M_Code_Project* project;
    FileVisualState m_VisualState;
    wxTreeItemId m_TreeItemId;
    wxString m_ObjName;
    PFDMap m_PFDMap;
};
WX_DECLARE_HASH_SET( ProjectFile*, wxPointerHash, wxPointerEqual, FilesList );
WX_DEFINE_SORTED_ARRAY( ProjectFile*, ProjectFileArray );

class pfDetails {
  public:
    pfDetails( ProjectBuildTarget* target, ProjectFile* pf );
    void Update( ProjectBuildTarget* target, ProjectFile* pf );
    wxString source_file;
    wxString object_file;
    wxString dep_file;
    wxString object_dir;
    wxString object_dir_flat;
    wxString dep_dir;
    wxString object_file_flat;
    wxString source_file_native;
    wxString object_file_native;
    wxString dep_file_native;
    wxString object_dir_native;
    wxString object_dir_flat_native;
    wxString dep_dir_native;
    wxString source_file_absolute_native;
    wxString object_file_absolute_native;
    wxString object_file_flat_absolute_native;
    wxString dep_file_absolute_native;
    wxString object_file_flat_native;
};

#endif
